﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using System.Runtime.Serialization;
using System.Collections;

namespace Mvvm
{
    [DataContract]
    public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo
    {
        public event PropertyChangedEventHandler PropertyChanged;
        public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

        private Dictionary<string, List<string>> _errors;

        protected ViewModelBase()
        {
            InitializeInternal();
        }

        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        private void OnErrorsChanged(DataErrorsChangedEventArgs e)
        {
            if (ErrorsChanged != null)
                ErrorsChanged(this, e);
        }

        public void ClearErrors()
        {
            _errors.Clear();
        }

        [OnDeserializing]
        public void Deserializing(StreamingContext context)
        {
            //Force object construction during deserialization
            InitializeInternal();
        }

        private void InitializeInternal()
        {
            _errors = new Dictionary<string, List<string>>();
        }

        protected virtual void AddError(string propertyName, string error)
        {
            //Create a list if this is the first entry for this property
            if (!_errors.ContainsKey(propertyName))
                _errors.Add(propertyName, new List<string>());

            var errorListForProperty =_errors[propertyName];
            if (!errorListForProperty.Contains(error))
            {
                errorListForProperty.Add(error);
                OnErrorsChanged(new DataErrorsChangedEventArgs(propertyName));
            }
        }

        protected virtual void RemoveError(string propertyName, string error)
        {
            if (_errors.ContainsKey(propertyName))
            {
                var errorListForProperty = _errors[propertyName];
                if (errorListForProperty.Remove(error))
                    OnErrorsChanged(new DataErrorsChangedEventArgs(propertyName));
            }
        }

        public IEnumerable GetErrors(string propertyName)
        {
            IEnumerable ret = null;

            if (_errors.ContainsKey(propertyName) && _errors[propertyName].Count > 0)
                ret = _errors[propertyName];

            return ret;
        }

        public bool HasErrors
        {
            get { return _errors.Count > 0; }
        }
    }
}
